package authentication.controller;

import authentication.service.TestClsService;
import authentication.utils.DBUtils;
import org.apache.shardingsphere.infra.hint.HintManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.sql.DataSource;
import java.sql.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: Qiao Hang
 * @CreateDate: 2021/4/20 下午5:09
 * @UpdateDate:
 * @Description:
 */
@RestController
public class TestClsController {

    @Autowired
    TestClsService testClsService;

    @GetMapping("getAll")
    public Object getAll(){
        return testClsService.getAll();
    }
    @PostMapping("insert")
    public Object insert(@RequestBody Map<String,String> row){
        return testClsService.insert(row);
    }
    @PostMapping("update")
    public Object update(@RequestBody Map<String,String> row){
        return testClsService.update(row);
    }

    @Autowired
    DataSource dataSource;

    @PostMapping("query")
    public Object query(@RequestBody Map<String,String> body){
        String sql = body.get("sql");
        if(sql == null) return null;

        Object res = null;
        try (
                Connection connection = dataSource.getConnection();
                PreparedStatement preparedStatement = connection.prepareStatement(sql)
        ){
            ResultSet resultSet = preparedStatement.executeQuery();
            res =  DBUtils.convertList(resultSet);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return res;
    }


    @PostMapping("persist")
    public Object persist(@RequestBody Map<String,String> body){
        String sql = body.get("sql");
        if(sql == null) return null;

        Object res = null;
        try (
                Connection connection = dataSource.getConnection();
                PreparedStatement preparedStatement = connection.prepareStatement(sql)
        ){
            boolean execute = preparedStatement.execute();
            res =  execute;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return res;
    }


    @PostMapping("persistPlus")
    public Object persistPlus(@RequestBody Map<String,Object> body){
        String sql = (String)body.get("sql");
        if(sql == null) return null;

        List<String> params = (List<String>) body.get("params");

        Object res = null;
        try (
                Connection connection = dataSource.getConnection();
                PreparedStatement preparedStatement = connection.prepareStatement(sql)
        ){
            for (int i = 1; i <= params.size(); i++) {
                String[] split = params.get(i-1).split(";");
                String type = split[0];
                if(type.equals("int")){
                    preparedStatement.setInt(i,Integer.parseInt(split[1]));
                }else if(type.equals("long")){
                    preparedStatement.setLong(i,Long.parseLong(split[1]));
                }else if(type.equals("float")){
                    preparedStatement.setFloat(i,Float.parseFloat(split[1]));
                }else if(type.equals("double")){
                    preparedStatement.setDouble(i,Double.parseDouble(split[1]));
                } else if(type.equals("string")){
                    preparedStatement.setString(i,split[1]);
                }
            }
            boolean execute = preparedStatement.execute();
            res =  execute;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return res;
    }


    @PostMapping("queryHit")
    public Object queryHint(@RequestBody Map<String,Object> body){
        String sql = (String)body.get("sql");
        if(sql == null) return null;

        Object tab = body.get("tab");
        Object tabVal = body.get("tabVal");
        Object dbVal = body.get("dbVal");
        Object dbChoose = body.get("dbChoose");
        Object primary = body.get("primaryKey");

        Object res = null;
        try (
                Connection connection = dataSource.getConnection();
                PreparedStatement preparedStatement = connection.prepareStatement(sql)
        ){
            HintManager instance = null;
            if((tab != null && tabVal != null) || dbVal != null || dbChoose != null || primary != null){
                instance = HintManager.getInstance();
            }
            if(tab != null && tabVal != null){
                System.out.println("tab:" + tab + " ,tabVal:"+tabVal);
                instance.addTableShardingValue(tab.toString(),Comparable.class.cast(tabVal));
            }
            if(dbVal != null){
                System.out.println("dbVal:"+dbVal);
                instance.addDatabaseShardingValue(tab.toString(),Comparable.class.cast(dbVal));
            }
            if(dbChoose != null){
                System.out.println("dbChoose:" + dbChoose);
                instance.setDatabaseShardingValue(Comparable.class.cast(dbChoose));
            }
            if(primary != null){
                instance.setPrimaryRouteOnly();
            }
            boolean execute = preparedStatement.execute();
            res =  execute;
            if(instance != null){
                instance.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return res;
    }

    @GetMapping("transaction")
//    @Transactional
//    @ShardingTransactionType(TransactionType.XA)
    public Object transaction(@RequestParam Boolean doError){
        //id generic, 数据根据uid落库，到dn0:user -> pay_info_0上.
        String pay_info_sql = "insert into pay_info(`uid`,`order_id`,`pay_amount`) values(30,31,10.12)";
        //id generic, 数据根据order_id落库，到dn1:user -> delivery_info_1上 保证test test1垮库.
        String delivery_info_sql = "insert into delivery_info(`order_id`,`delivery_id`,`status`) values(31,301,0)";

        HashMap<String, Object> payInfo = new HashMap<String, Object>() {{
            put("uid", 30);
            put("order_id", 31);
            put("pay_amount", 10.12);
        }};
        testClsService.insertPayInfo(payInfo);

        HashMap<String, Object> deliveryInfo = new HashMap<String, Object>() {{
            put("order_id", 31);
            put("delivery_id", 301);
            put("status", 0);
        }};
        testClsService.insertDeliveryInfo(deliveryInfo);

        if(doError != null && doError.equals(Boolean.TRUE)){
            int error = 1 / 0;
        }
        return Boolean.TRUE;
    }

}
